﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;
using YJKRevitBase.Math;
using YJKRevitKernel.BoundingBoxUtility;
using YJKRevitKernel.CurveUtility;
using YJKRevitKernel.XYZUtility;

namespace YJKGeometryFuncs
{
	public class Geometry
	{
		public static bool LessThan(double val1, double val2)
		{
			return MathUtility.LessThan(val1, val2);
		}

		public static bool LessThan(double val1, double val2, double eps)
		{
			return MathUtility.LessThan(val1, val2, eps);
		}

		public static bool GreaterThan(double val1, double val2)
		{
			return MathUtility.GreaterThan(val1, val2);
		}

		public static bool GreaterThan(double val1, double val2, double eps)
		{
			return MathUtility.GreaterThan(val1, val2, eps);
		}

		public static bool IsEqual(double val1, double val2)
		{
			return MathUtility.IsEqual(val1, val2);
		}

		public static bool IsEqual(double val1, double val2, double eps)
		{
			return MathUtility.IsEqual(val2, val1, eps);
		}

		public static bool IsEqual(XYZ pt1, XYZ pt2)
		{
			return XYZUtilityMethod.IsEqual(pt1, pt2);
		}

		public static bool IsEqual(XYZ pt1, XYZ pt2, double eps)
		{
			return XYZUtilityMethod.IsEqual(pt1, pt2, eps);
		}

		public static bool Lessthan_Or_Equal(double val1, double val2)
		{
			return MathUtility.Lessthan_Or_Equal(val1, val2);
		}

		public static bool Lessthan_Or_Equal(double val1, double val2, double eps)
		{
			return MathUtility.Lessthan_Or_Equal(val1, val2, eps);
		}

		public static bool Greaterthan_Or_Equal(double val1, double val2)
		{
			return MathUtility.Greaterthan_Or_Equal(val1, val2);
		}

		public static bool Greaterthan_Or_Equal(double val1, double val2, double eps)
		{
			return MathUtility.Greaterthan_Or_Equal(val1, val2, eps);
		}

		public static bool IsParallel(XYZ a, XYZ b)
		{
			return XYZUtilityMethod.IsParallel(a, b);
		}

		public static bool IsVertical(XYZ a, XYZ b)
		{
			return XYZUtilityMethod.IsVertical(a, b);
		}

		public static XYZ RotateTo(XYZ vt, double angle, XYZ axis)
		{
			return XYZUtilityMethod.RotateTo(vt, XYZ.Zero, angle, axis);
		}

		public static XYZ RotateTo(XYZ vt, XYZ origin, double angle, XYZ axis)
		{
			return XYZUtilityMethod.RotateTo(vt, origin, angle, axis);
		}

		public static XYZ CalculateFootPoint(Line line, XYZ point)
		{
			XYZ hyendPoint = line.GetEndPoint(0);
			XYZ hyendPoint2 = line.GetEndPoint(1);
			return Geometry.CalculateFootPoint(hyendPoint, hyendPoint2, point);
		}

		public static XYZ CalculateFootPoint(XYZ ptStart, XYZ ptEnd, XYZ point)
		{
			return XYZUtilityMethod.CalculateFootPoint(ptStart, ptEnd, point);
		}

		public static XYZ CalculateFootPoint(Arc arc, XYZ point)
		{
			XYZ center = arc.Center;
			XYZ hyendPoint = arc.GetEndPoint(0);
			XYZ hyendPoint2 = arc.GetEndPoint(1);
			return Geometry.CalculateFootPoint(hyendPoint, hyendPoint2, center, point);
		}

		public static XYZ CalculateFootPoint(XYZ ptStart, XYZ ptEnd, XYZ ptCenter, XYZ point)
		{
			return XYZUtilityMethod.CalculateFootPoint(ptStart, ptEnd, ptCenter, point);
		}

		public static bool PointAtLineLeft(XYZ pt, XYZ ptStart, XYZ ptEnd)
		{
			return XYZUtilityMethod.PointAtLineLeft(pt, ptStart, ptEnd);
		}

		public static XYZ TransformPoint(XYZ point, Transform transform)
		{
			return XYZUtilityMethod.TransformPoint(point, transform);
		}

		public static XYZ TransformPointToShaftSide(XYZ point, double angle)
		{
			double num = point.X + point.Y * Math.Cos(angle / 180.0 * Math.PI);
			double num2 = point.Y * Math.Sin(angle / 180.0 * Math.PI) + point.Z;
			return new XYZ(num, num2, point.Z);
		}

		public static BoundingBoxUV CalculateBoundingBox2D(XYZ ptStart, XYZ ptEnd)
		{
			return BoundingBoxUtilityMethod.CalculateBoundingBox2D(ptStart, ptEnd);
		}

		public static BoundingBoxUV CalculateBoundingBox2D(Line line)
		{
			XYZ hyendPoint = line.GetEndPoint(0);
			XYZ hyendPoint2 = line.GetEndPoint(1);
			return Geometry.CalculateBoundingBox2D(hyendPoint, hyendPoint2);
		}

		public static void GetArcAngles(Arc arc, ref double startAngle, ref double endAngle)
		{
			XYZ hyendPoint = arc.GetEndPoint(0);
			XYZ hyendPoint2 = arc.GetEndPoint(1);
			XYZ center = arc.Center;
			startAngle = XYZ.BasisX.AngleOnPlaneTo(hyendPoint - center, XYZ.BasisZ);
			endAngle = XYZ.BasisX.AngleOnPlaneTo(hyendPoint2 - center, XYZ.BasisZ);
			if (Geometry.IsEqual(arc.Normal.Z, -1.0))
			{
				endAngle = (double)((float)XYZ.BasisX.AngleOnPlaneTo(hyendPoint - center, XYZ.BasisZ));
				startAngle = (double)((float)XYZ.BasisX.AngleOnPlaneTo(hyendPoint2 - center, XYZ.BasisZ));
			}
			if (startAngle > endAngle)
			{
				startAngle -= Math.PI*2;
			}
		}

		public static BoundingBoxUV CalculateBoundingBox2D(XYZ ptStart, XYZ ptEnd, XYZ ptCenter, XYZ normal, double radius)
		{
			return BoundingBoxUtilityMethod.CalculateBoundingBox2D(ptStart, ptEnd, ptCenter, normal, radius);
		}

		public static BoundingBoxUV CalculateBoundingBox2D(Arc arc)
		{
			XYZ hyendPoint = arc.GetEndPoint(0);
			XYZ hyendPoint2 = arc.GetEndPoint(1);
			XYZ center = arc.Center;
			XYZ normal = arc.Normal;
			double radius = arc.Radius;
			if (arc.IsCyclic)
			{
				return new BoundingBoxUV(center.X - radius, center.Y - radius, center.X + radius, center.Y + radius);
			}
			return Geometry.CalculateBoundingBox2D(hyendPoint, hyendPoint2, center, normal, radius);
		}

		public static BoundingBoxUV BoundingBoxesMerge(BoundingBoxUV box1, BoundingBoxUV box2)
		{
			return BoundingBoxUtilityMethod.BoundingBoxesMerge(box1, box2);
		}

		public static BoundingBoxXYZ BoundingBoxesMerge(BoundingBoxXYZ box1, BoundingBoxXYZ box2)
		{
			return BoundingBoxUtilityMethod.BoundingBoxesMerge(box1, box2);
		}

		public static XYZ CalculatMidPoint(XYZ ptStart, XYZ ptEnd)
		{
			return XYZUtilityMethod.CalculatMidPoint(ptStart, ptEnd);
		}

		public static XYZ CalculatMidPoint(Line line)
		{
			XYZ hyendPoint = line.GetEndPoint(0);
			XYZ hyendPoint2 = line.GetEndPoint(1);
			return Geometry.CalculatMidPoint(hyendPoint, hyendPoint2);
		}

		public static XYZ CalculatMidPoint(XYZ ptStart, XYZ ptEnd, XYZ ptCenter, XYZ normal)
		{
			return XYZUtilityMethod.CalculatMidPoint(ptStart, ptEnd, ptCenter, normal);
		}

		public static XYZ CalculatMidPoint(Arc arc)
		{
			XYZ hyendPoint = arc.GetEndPoint(0);
			XYZ center = arc.Center;
			XYZ vt = (hyendPoint - center).Normalize();
			double radius = arc.Radius;
			double num = arc.Length / radius / 2.0;
			XYZ xyz = Geometry.RotateTo(vt, num, XYZ.BasisZ).Normalize();
			if (Geometry.IsEqual(arc.Normal.Z, -1.0))
			{
				xyz = Geometry.RotateTo(vt, -num, XYZ.BasisZ).Normalize();
			}
			return center + xyz * radius;
		}

		public static Line OffsetLine(Line line, double offset)
		{
			XYZ hyendPoint = line.GetEndPoint(0);
			XYZ hyendPoint2 = line.GetEndPoint(1);
			XYZ xyz = Geometry.RotateTo(line.Direction, Math.PI*.5, XYZ.BasisZ) * offset;
			XYZ startPoint = hyendPoint + xyz;
			XYZ endPoint = hyendPoint2 + xyz;
			return YJKLineEx.YJKGetBound(startPoint, endPoint);
		}

		public static Arc OffsetArc(Arc arc, double offset, Autodesk.Revit.ApplicationServices.Application app = null)
		{
			if (arc.Normal.Z > 0.0)
			{
				offset = -offset;
			}
			XYZ hyendPoint = arc.GetEndPoint(0);
			XYZ hyendPoint2 = arc.GetEndPoint(1);
			XYZ center = arc.Center;
			XYZ xyz = Geometry.CalculatMidPoint(arc);
			double num = arc.Radius + offset;
			XYZ xyz2 = (hyendPoint - center).Normalize() * num;
			XYZ xyz3 = (hyendPoint2 - center).Normalize() * num;
			XYZ xyz4 = (xyz - center).Normalize() * num;
			XYZ startPnt = center + xyz2;
			XYZ endPnt = center + xyz3;
			XYZ radianPnt = center + xyz4;
			return app.CreatYJKArc(startPnt, endPnt, radianPnt);
		}

		public static double formatAngle(double angle)
		{
			return MathUtility.formatAngle(angle);
		}

		public static double getAngle(XYZ ptCenter, XYZ ptOut)
		{
			return XYZUtilityMethod.GetAngle(ptCenter, ptOut);
		}

		public static double BetweenTheAngles(double dSAngle, double dEAngle, bool range2PI)
		{
			return MathUtility.BetweenTheAngles(dSAngle, dEAngle, range2PI);
		}

		public static double GetBulge(XYZ SP, XYZ EP, XYZ CenterPt, bool isAnticlockwise)
		{
			return CurveUtilityMethod.GetBulge(SP, EP, CenterPt, isAnticlockwise);
		}

		public static void GetRadiusWithBulge(XYZ SP, XYZ EP, double dBulge, ref double dRadius)
		{
			CurveUtilityMethod.GetRadiusWithBulge(SP, EP, dBulge, ref dRadius);
		}

		public static void GetCenterWithBulge(XYZ SP, XYZ EP, double dBulge, ref XYZ ptCenter)
		{
			CurveUtilityMethod.GetCenterWithBulge(SP, EP, dBulge, ref ptCenter);
		}

		public static void GetArcInfoWithBulge(XYZ SP, XYZ EP, double dBulge, ref XYZ ptCenter, ref double dRadius, ref double dSAngle, ref double dEAngle)
		{
			CurveUtilityMethod.GetArcInfoWithBulge(SP, EP, dBulge, ref ptCenter, ref dRadius, ref dSAngle, ref dEAngle);
		}

		public static bool Is_Point_OnSegment(XYZ ptSOfLine, XYZ ptEOfLine, XYZ pt, double tolerance = 1E-09)
		{
			return XYZUtilityMethod.Is_Point_OnSegment(ptSOfLine, ptEOfLine, pt, tolerance);
		}

		public static bool Is_Point_OnSegment(XYZ ptSOfArc, XYZ ptEOfArc, XYZ ptCenterOfArc, XYZ normal, XYZ pt, double tolerance = 1E-09)
		{
			return XYZUtilityMethod.Is_Point_OnSegment(ptSOfArc, ptEOfArc, ptCenterOfArc, normal, pt, tolerance);
		}

		protected static List<Curve> ExtendEndsWithCurve(Curve curve, Autodesk.Revit.ApplicationServices.Application revitApp)
		{
			List<Curve> list = new List<Curve>();
			if (!curve.IsBound)
			{
				list.Add(curve);
				return list;
			}
			Line line = curve as Line;
			if (null != line)
			{
				XYZ hyendPoint = line.GetEndPoint(0);
				XYZ hyendPoint2 = line.GetEndPoint(1);
				Line item = YJKLineEx.YJKGetUnBound(hyendPoint, hyendPoint2 - hyendPoint);
				list.Add(item);
				return list;
			}
			Arc arc = curve as Arc;
			if (null != arc)
			{
				XYZ center = arc.Center;
				double radius = arc.Radius;
				XYZ xyz = center + XYZ.BasisX * radius;
				XYZ radianPnt = center + XYZ.BasisY * radius;
				XYZ xyz2 = center + -XYZ.BasisX * radius;
				XYZ radianPnt2 = center + -XYZ.BasisY * radius;
				Arc item2 = revitApp.CreatYJKArc(xyz, xyz2, radianPnt);
				list.Add(item2);
				Arc item3 = revitApp.CreatYJKArc(xyz2, xyz, radianPnt2);
				list.Add(item3);
				return list;
			}
			return list;
		}

		public static XYZ IntersectWithTwoCurves(Curve curve1, Curve curve2, XYZ curNode, bool extendCurve1, bool extendCurve2, Autodesk.Revit.ApplicationServices.Application revitApp = null)
		{
			List<Curve> list = new List<Curve>();
			if (extendCurve1)
			{
				list = Geometry.ExtendEndsWithCurve(curve1, revitApp);
			}
			else
			{
				list.Add(curve1);
			}
			List<Curve> list2 = new List<Curve>();
			if (extendCurve2)
			{
				list2 = Geometry.ExtendEndsWithCurve(curve2, revitApp);
			}
			else
			{
				list2.Add(curve2);
			}
			List<XYZ> list3 = new List<XYZ>();
			foreach (Curve curve3 in list)
			{
				foreach (Curve curve4 in list2)
				{
					IntersectionResultArray intersectionResultArray;
                    if ((int)curve3.Intersect(curve4, out intersectionResultArray) == 8)
					{
						foreach (object obj in intersectionResultArray)
						{
							IntersectionResult intersectionResult = (IntersectionResult)obj;
							list3.Add(intersectionResult.XYZPoint);
						}
					}
				}
			}
			double num = double.MaxValue;
			XYZ result = null;
			foreach (XYZ xyz in list3)
			{
				double num2 = curNode.DistanceTo(xyz);
				if (num2 < num)
				{
					num = num2;
					result = xyz;
				}
			}
			return result;
		}

		public static Geometry.OverlapType IsOverlapOfTwoLine(XYZ ptS1, XYZ ptE1, XYZ ptS2, XYZ ptE2, ref XYZ ptS, ref XYZ ptE, bool returnOverLapPoints = true, double distanceTolerance = 1E-09, double collinearTolerance = 1E-09)
		{
			if ((Geometry.IsEqual(ptS1.DistanceTo(ptS2), 0.0, distanceTolerance) && Geometry.IsEqual(ptE1.DistanceTo(ptE2), 0.0, distanceTolerance)) || (Geometry.IsEqual(ptS1.DistanceTo(ptE2), 0.0, distanceTolerance) && Geometry.IsEqual(ptE1.DistanceTo(ptS2), 0.0, distanceTolerance)))
			{
				ptS = ptS1;
				ptE = ptE1;
				return Geometry.OverlapType._OT_Equality;
			}
			if (Geometry.Is_Point_OnSegment(ptS1, ptE1, ptS2, collinearTolerance) && Geometry.Is_Point_OnSegment(ptS1, ptE1, ptE2, collinearTolerance))
			{
				if (returnOverLapPoints)
				{
					ptS = ptS2;
					ptE = ptE2;
				}
				else
				{
					ptS = ptS1;
					ptE = ptE1;
				}
				return Geometry.OverlapType._OT_FirstIncludeSecond;
			}
			if (Geometry.Is_Point_OnSegment(ptS2, ptE2, ptS1, collinearTolerance) && Geometry.Is_Point_OnSegment(ptS2, ptE2, ptE1, collinearTolerance))
			{
				if (returnOverLapPoints)
				{
					ptS = ptS1;
					ptE = ptE1;
				}
				else
				{
					ptS = ptS2;
					ptE = ptE2;
				}
				return Geometry.OverlapType._OT_SecondIncludeFirst;
			}
			if (Geometry.Is_Point_OnSegment(ptS1, ptE1, ptS2, collinearTolerance))
			{
				if (Geometry.Is_Point_OnSegment(ptS2, ptE2, ptS1, collinearTolerance))
				{
					if (returnOverLapPoints)
					{
						ptS = ptS2;
						ptE = ptS1;
					}
					else
					{
						ptS = ptE1;
						ptE = ptE2;
					}
					if (!Geometry.IsEqual(ptS2.DistanceTo(ptS1), 0.0))
					{
						return Geometry.OverlapType._OT_Part;
					}
					return Geometry.OverlapType._OT_Linked;
				}
				else if (Geometry.Is_Point_OnSegment(ptS2, ptE2, ptE1, collinearTolerance))
				{
					if (returnOverLapPoints)
					{
						ptS = ptS2;
						ptE = ptE1;
					}
					else
					{
						ptS = ptS1;
						ptE = ptE2;
					}
					if (!Geometry.IsEqual(ptS2.DistanceTo(ptE1), 0.0, distanceTolerance))
					{
						return Geometry.OverlapType._OT_Part;
					}
					return Geometry.OverlapType._OT_Linked;
				}
			}
			else if (Geometry.Is_Point_OnSegment(ptS1, ptE1, ptE2, collinearTolerance))
			{
				if (Geometry.Is_Point_OnSegment(ptS2, ptE2, ptS1, collinearTolerance))
				{
					if (returnOverLapPoints)
					{
						ptS = ptE2;
						ptE = ptS1;
					}
					else
					{
						ptS = ptE1;
						ptE = ptS2;
					}
					if (!Geometry.IsEqual(ptE2.DistanceTo(ptS1), 0.0, distanceTolerance))
					{
						return Geometry.OverlapType._OT_Part;
					}
					return Geometry.OverlapType._OT_Linked;
				}
				else if (Geometry.Is_Point_OnSegment(ptS2, ptE2, ptE1, collinearTolerance))
				{
					if (returnOverLapPoints)
					{
						ptS = ptE2;
						ptE = ptE1;
					}
					else
					{
						ptS = ptS1;
						ptE = ptS2;
					}
					if (!Geometry.IsEqual(ptE2.DistanceTo(ptE1), 0.0, distanceTolerance))
					{
						return Geometry.OverlapType._OT_Part;
					}
					return Geometry.OverlapType._OT_Linked;
				}
			}
			return Geometry.OverlapType._OT_None;
		}

		public static Geometry.OverlapType MergerOfTwoLine(XYZ ptS1, XYZ ptE1, XYZ ptS2, XYZ ptE2, ref XYZ ptS, ref XYZ ptE)
		{
			if ((Geometry.IsEqual(ptS1.DistanceTo(ptS2), 0.0) && Geometry.IsEqual(ptE1.DistanceTo(ptE2), 0.0)) || (Geometry.IsEqual(ptS1.DistanceTo(ptE2), 0.0) && Geometry.IsEqual(ptE1.DistanceTo(ptS2), 0.0)))
			{
				ptS = ptS1;
				ptE = ptE1;
				return Geometry.OverlapType._OT_Equality;
			}
			if (Geometry.Is_Point_OnSegment(ptS1, ptE1, ptS2, 1E-09) && Geometry.Is_Point_OnSegment(ptS1, ptE1, ptE2, 1E-09))
			{
				ptS = ptS1;
				ptE = ptE1;
				return Geometry.OverlapType._OT_FirstIncludeSecond;
			}
			if (Geometry.Is_Point_OnSegment(ptS2, ptE2, ptS1, 1E-09) && Geometry.Is_Point_OnSegment(ptS2, ptE2, ptE1, 1E-09))
			{
				ptS = ptS2;
				ptE = ptE2;
				return Geometry.OverlapType._OT_SecondIncludeFirst;
			}
			if (Geometry.Is_Point_OnSegment(ptS1, ptE1, ptS2, 1E-09))
			{
				if (Geometry.Is_Point_OnSegment(ptS2, ptE2, ptS1, 1E-09))
				{
					ptS = ptE2;
					ptE = ptE1;
					if (!Geometry.IsEqual(ptS2.DistanceTo(ptS1), 0.0))
					{
						return Geometry.OverlapType._OT_Part;
					}
					return Geometry.OverlapType._OT_Linked;
				}
				else if (Geometry.Is_Point_OnSegment(ptS2, ptE2, ptE1, 1E-09))
				{
					ptS = ptE2;
					ptE = ptS1;
					if (!Geometry.IsEqual(ptS2.DistanceTo(ptE1), 0.0))
					{
						return Geometry.OverlapType._OT_Part;
					}
					return Geometry.OverlapType._OT_Linked;
				}
			}
			else if (Geometry.Is_Point_OnSegment(ptS1, ptE1, ptE2, 1E-09))
			{
				if (Geometry.Is_Point_OnSegment(ptS2, ptE2, ptS1, 1E-09))
				{
					ptS = ptS2;
					ptE = ptE1;
					if (!Geometry.IsEqual(ptE2.DistanceTo(ptS1), 0.0))
					{
						return Geometry.OverlapType._OT_Part;
					}
					return Geometry.OverlapType._OT_Linked;
				}
				else if (Geometry.Is_Point_OnSegment(ptS2, ptE2, ptE1, 1E-09))
				{
					ptS = ptS2;
					ptE = ptS1;
					if (!Geometry.IsEqual(ptE2.DistanceTo(ptE1), 0.0))
					{
						return Geometry.OverlapType._OT_Part;
					}
					return Geometry.OverlapType._OT_Linked;
				}
			}
			return Geometry.OverlapType._OT_None;
		}

		private static bool IsCoverAngle(double sAngle, double eAngle, double testAngle)
		{
			double val = Geometry.BetweenTheAngles(sAngle, eAngle, true);
			double num = Geometry.BetweenTheAngles(sAngle, testAngle, true);
			double num2 = Geometry.BetweenTheAngles(testAngle, eAngle, true);
			return Geometry.IsEqual(val, num + num2);
		}

		public static Geometry.OverlapType IsOverlapOfTwoArc(XYZ ptS1, XYZ ptE1, XYZ ptCenter1, XYZ normal1, XYZ ptS2, XYZ ptE2, XYZ ptCenter2, XYZ normal2, ref XYZ ptS, ref XYZ ptE, double tolerance = 1E-09)
		{
			if (!Geometry.IsEqual(normal1.Normalize(), XYZ.BasisZ))
			{
				XYZ xyz = ptS1;
				ptS1 = ptE1;
				ptE1 = xyz;
			}
			if (!Geometry.IsEqual(normal2.Normalize(), XYZ.BasisZ))
			{
				XYZ xyz2 = ptS2;
				ptS2 = ptE2;
				ptE2 = xyz2;
			}
			if (!Geometry.IsEqual(ptCenter1.DistanceTo(ptCenter2), 0.0, tolerance))
			{
				return Geometry.OverlapType._OT_None;
			}
			double val = ptS1.DistanceTo(ptCenter1);
			double val2 = ptS2.DistanceTo(ptCenter2);
			if (!Geometry.IsEqual(val, val2, tolerance))
			{
				return Geometry.OverlapType._OT_None;
			}
			double angle = Geometry.getAngle(ptCenter1, ptS1);
			double angle2 = Geometry.getAngle(ptCenter1, ptE1);
			double angle3 = Geometry.getAngle(ptCenter2, ptS2);
			double angle4 = Geometry.getAngle(ptCenter2, ptE2);
			if (Geometry.IsEqualAngles(angle, angle3) && Geometry.IsEqualAngles(angle2, angle4))
			{
				ptS = ptS1;
				ptE = ptE1;
				return Geometry.OverlapType._OT_Equality;
			}
			if (Geometry.IsEqualAngles(angle, angle4) || Geometry.IsEqualAngles(angle2, angle3))
			{
				return Geometry.OverlapType._OT_Linked;
			}
			if (Geometry.IsCoverAngle(angle, angle2, angle3) && Geometry.IsCoverAngle(angle, angle2, angle4))
			{
				ptS = ptS2;
				ptE = ptE2;
				return Geometry.OverlapType._OT_FirstIncludeSecond;
			}
			if (Geometry.IsCoverAngle(angle3, angle4, angle) && Geometry.IsCoverAngle(angle3, angle4, angle2))
			{
				ptS = ptS1;
				ptE = ptE1;
				return Geometry.OverlapType._OT_SecondIncludeFirst;
			}
			if (Geometry.IsCoverAngle(angle3, angle4, angle))
			{
				ptS = ptS1;
				ptE = ptE2;
				return Geometry.OverlapType._OT_Part;
			}
			if (Geometry.IsCoverAngle(angle, angle2, angle3))
			{
				ptS = ptS2;
				ptE = ptE1;
				return Geometry.OverlapType._OT_Part;
			}
			return Geometry.OverlapType._OT_None;
		}

		public static bool IsEqualAngles(double angle1, double angle2)
		{
			return MathUtility.IsEqualAngles(angle1, angle2);
		}

		public static Geometry.OverlapType MergerOfTwoArc(XYZ ptS1, XYZ ptE1, XYZ ptCenter1, XYZ normal1, XYZ ptS2, XYZ ptE2, XYZ ptCenter2, XYZ normal2, ref XYZ ptS, ref XYZ ptE, double tolerance)
		{
			return Geometry.IsOverlapOfTwoArc(ptS1, ptE1, ptCenter1, normal1, ptS2, ptE2, ptCenter2, normal2, ref ptS, ref ptE, tolerance);
		}

		private static bool IsOverlap(XYZ ptS1, XYZ ptE1, double bugle1, XYZ ptS2, XYZ ptE2, double bugle2)
		{
			if (Geometry.IsEqual(bugle1, 0.0) && Geometry.IsEqual(bugle2, 0.0))
			{
				if (Geometry.IsEqual(ptS1.DistanceTo(ptE2), 0.0, 0.0001) && Geometry.IsEqual(ptE1.DistanceTo(ptS2), 0.0, 0.0001))
				{
					return true;
				}
			}
			else if (!Geometry.IsEqual(bugle1, 0.0) && !Geometry.IsEqual(bugle2, 0.0) && Geometry.IsEqual(ptS1.DistanceTo(ptE2), 0.0, 0.0001) && Geometry.IsEqual(ptE1.DistanceTo(ptS2), 0.0, 0.0001) && Geometry.IsEqual(bugle1, -bugle2))
			{
				return true;
			}
			return false;
		}

		public static void ConvertToSimpleClosedPolylineAndSimpleCurve(List<XYZ> points, List<double> bulges, ref List<List<XYZ>> simplePolysPoint, ref List<List<double>> simplePolysBulge, ref List<EdgeInfo> simpleCurves)
		{
			if (points.Count != bulges.Count)
			{
				return;
			}
			int i = 0;
			if (points.Count < 3)
			{
				while (i < points.Count)
				{
					XYZ startPoint = points[i];
					XYZ endPoint;
					if (i == points.Count - 1)
					{
						endPoint = points[0];
					}
					else
					{
						endPoint = points[i + 1];
					}
					double bulge = bulges[i];
					EdgeInfo item = new EdgeInfo(startPoint, endPoint, bulge);
					simpleCurves.Add(item);
					i++;
				}
				return;
			}
			bool flag = false;
			for (i = 0; i < points.Count; i++)
			{
				XYZ xyz = points[i];
				XYZ xyz2;
				if (i == points.Count - 1)
				{
					xyz2 = points[0];
				}
				else
				{
					xyz2 = points[i + 1];
				}
				if (!Geometry.IsEqual(xyz.DistanceTo(xyz2), 0.0, 0.0001))
				{
					double num = bulges[i];
					flag = false;
					for (int j = i + 1; j < points.Count; j++)
					{
						XYZ xyz3 = points[j];
						XYZ xyz4;
						if (j == points.Count - 1)
						{
							xyz4 = points[0];
						}
						else
						{
							xyz4 = points[j + 1];
						}
						if (!Geometry.IsEqual(xyz3.DistanceTo(xyz4), 0.0, 0.0001))
						{
							double bugle = bulges[j];
							if (Geometry.IsOverlap(xyz, xyz2, num, xyz3, xyz4, bugle))
							{
								EdgeInfo item2 = new EdgeInfo(xyz, xyz2, num);
								simpleCurves.Add(item2);
								List<XYZ> list = new List<XYZ>();
								List<XYZ> points2 = new List<XYZ>();
								List<double> list2 = new List<double>();
								List<double> bulges2 = new List<double>();
								if (i >= 0)
								{
									list = points.GetRange(0, i + 1);
									list2 = bulges.GetRange(0, i);
									if (j < points.Count - 2)
									{
										List<XYZ> range = points.GetRange(j + 2, points.Count - (j + 2));
										list.InsertRange(list.Count, range);
										List<double> range2 = bulges.GetRange(j + 1, bulges.Count - (j + 1));
										list2.InsertRange(list2.Count, range2);
									}
									else if (j == points.Count - 1)
									{
										list.RemoveAt(list.Count - 1);
									}
									else
									{
										list2.Add(bulges[bulges.Count - 1]);
									}
								}
								if (j < points.Count - 1 && j > i + 1)
								{
									points2 = points.GetRange(i + 1, j - (i + 1));
									bulges2 = bulges.GetRange(i + 1, j - (i + 1));
								}
								Geometry.ConvertToSimpleClosedPolylineAndSimpleCurve(list, list2, ref simplePolysPoint, ref simplePolysBulge, ref simpleCurves);
								Geometry.ConvertToSimpleClosedPolylineAndSimpleCurve(points2, bulges2, ref simplePolysPoint, ref simplePolysBulge, ref simpleCurves);
								flag = true;
								break;
							}
						}
					}
					if (flag)
					{
						break;
					}
				}
			}
			if (!flag && points.Count > 1)
			{
				simplePolysPoint.Add(points);
				simplePolysBulge.Add(bulges);
			}
		}

		public static bool GetFittingPolyline(List<XYZ> polylinePoints, List<double> polylineBulge, ref List<XYZ> fittingPolyline, double fitSpace)
		{
			if (polylinePoints.Count != polylineBulge.Count)
			{
				return false;
			}
			if (polylinePoints.Count < 2)
			{
				return false;
			}
			fittingPolyline.Add(polylinePoints[0]);
			for (int i = 0; i < polylinePoints.Count; i++)
			{
				XYZ xyz;
				XYZ xyz2;
				if (i == polylinePoints.Count - 1)
				{
					xyz = polylinePoints[i];
					xyz2 = polylinePoints[0];
				}
				else
				{
					xyz = polylinePoints[i];
					xyz2 = polylinePoints[i + 1];
				}
				if (!Geometry.IsEqual(xyz.DistanceTo(xyz2), 0.0, 0.0001))
				{
					if (Geometry.IsEqual(polylineBulge[i], 0.0))
					{
						if (i + 1 < polylinePoints.Count)
						{
							fittingPolyline.Add(polylinePoints[i + 1]);
						}
					}
					else
					{
						XYZ xyz3 = null;
						Geometry.GetCenterWithBulge(xyz, xyz2, polylineBulge[i], ref xyz3);
						double num = xyz3.DistanceTo(xyz);
						double angle = Geometry.getAngle(xyz3, xyz);
						double angle2 = Geometry.getAngle(xyz3, xyz2);
						double num2 = Geometry.BetweenTheAngles(angle, angle2, true) * num;
						int num3 = (int)(num2 / fitSpace);
						double num4 = num2 / (double)num3;
						if (num3 == 0)
						{
							num4 = num2;
							num3 = 1;
						}
						double num5 = num4 / num;
						for (int j = 0; j <= num3; j++)
						{
							double angle3 = angle + num5 * (double)j;
							XYZ xyz4 = new XYZ(1.0, 0.0, 0.0);
							xyz4 *= num;
							xyz4 = Geometry.RotateTo(xyz4, angle3, XYZ.BasisZ);
							XYZ item = xyz3 + xyz4;
							fittingPolyline.Add(item);
						}
					}
				}
			}
			return true;
		}

		public static int PointInPloygon(List<Curve> lstCurves, XYZ pt)
		{
			return XYZUtilityMethod.PointInPloygon(lstCurves, pt);
		}

		public static int PointInPloygon(List<XYZ> vecPolypt, XYZ pt)
		{
			return XYZUtilityMethod.PointInPloygon(vecPolypt, pt);
		}

		public static XYZ Centroid(CurveArray closePolyline)
		{
			return YJKRevitTools.Centroid(closePolyline);
		}

		public static double AoArea(List<Curve> arCurve)
		{
			List<XYZ> list = new List<XYZ>();
			foreach (Curve curve in arCurve)
			{
				XYZ endPoint = curve.GetEndPoint(0);
				XYZ endPoint2 = curve.GetEndPoint(1);
				list.Add(endPoint);
				list.Add(endPoint2);
			}
			list = list.Distinct<XYZ>().ToList<XYZ>();
			double[] array = new double[list.Count];
			double[] array2 = new double[list.Count];
			int num = 0;
			int num2 = 0;
			foreach (XYZ xyz in list)
			{
				array[num++] = xyz.X;
				array2[num2++] = xyz.Y;
			}
			return Geometry.AoArea(list.Count, array, array2);
		}

		public static double AoArea1(List<Curve> arCurve)
		{
			List<XYZ> list = new List<XYZ>();
			foreach (Curve curve in arCurve)
			{
				if (curve is Line)
				{
					XYZ endPoint = curve.GetEndPoint(0);
					XYZ endPoint2 = curve.GetEndPoint(1);
					list.Add(endPoint);
					list.Add(endPoint2);
				}
				if (curve is Arc)
				{
					foreach (XYZ item in curve.Tessellate())
					{
						list.Add(item);
					}
				}
			}
			list = list.Distinct<XYZ>().ToList<XYZ>();
			double[] array = new double[list.Count];
			double[] array2 = new double[list.Count];
			int num = 0;
			int num2 = 0;
			foreach (XYZ xyz in list)
			{
				array[num++] = xyz.X;
				array2[num2++] = xyz.Y;
			}
			return Geometry.AoArea(list.Count, array, array2);
		}

		public static double AoArea(int count, double[] X, double[] Y)
		{
			return MathUtility.AoArea(count, X, Y);
		}

		public static bool IsAntiClockwise(List<XYZ> loop)
		{
			return CurveUtilityMethod.IsAntiClockwise(loop);
		}

		public const double _epsDouble = 1E-09;

		public const double _epsPoint = 0.0001;

		public const double _epsAngle = 0.0001;

		public enum OverlapType
		{
			_OT_None,
			_OT_Equality,
			_OT_FirstIncludeSecond,
			_OT_SecondIncludeFirst,
			_OT_Part,
			_OT_Linked
		}
	}
}
